package com.java2e.martin.erd.service.impl;

import cn.fisok.pdman.dbreverse.ParseDataModel;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.java2e.martin.erd.entity.Project;
import com.java2e.martin.erd.mapper.ProjectMapper;
import com.java2e.martin.erd.service.ProjectService;
import com.java2e.martin.erd.util.JsonUtil;
import com.java2e.martin.erd.util.Result;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

/**
 * <p>
 * PDMan全局配置表 服务实现类
 * </p>
 *
 * @author 狮少
 * @since 2020-10-26
 */
@Service
public class ProjectServiceImpl extends ServiceImpl<ProjectMapper, Project> implements ProjectService {

    private final static String PROJECT_JSON = "{\"modules\":[],\"dataTypeDomains\":{\"datatype\":[{\"name\":\"默认字串\",\"code\":\"DefaultString\",\"apply\":{\"JAVA\":{\"type\":\"String\"},\"MYSQL\":{\"type\":\"VARCHAR(32)\"},\"ORACLE\":{\"type\":\"NVARCHAR2(32)\"},\"SQLServer\":{\"type\":\"NVARCHAR(32)\"},\"PostgreSQL\":{\"type\":\"VARCHAR(32)\"}}},{\"name\":\"标识号\",\"code\":\"IdOrKey\",\"apply\":{\"JAVA\":{\"type\":\"String\"},\"ORACLE\":{\"type\":\"VARCHAR2(32)\"},\"MYSQL\":{\"type\":\"VARCHAR(32)\"},\"SQLServer\":{\"type\":\"VARCHAR(32)\"},\"PostgreSQL\":{\"type\":\"VARCHAR(32)\"}}},{\"name\":\"标识号-长\",\"code\":\"LongKey\",\"apply\":{\"MYSQL\":{\"type\":\"VARCHAR(64)\"},\"ORACLE\":{\"type\":\"VARCHAR2(64)\"},\"JAVA\":{\"type\":\"String\"},\"SQLServer\":{\"type\":\"VARCHAR(64)\"},\"PostgreSQL\":{\"type\":\"VARCHAR(64)\"}}},{\"name\":\"名称\",\"code\":\"Name\",\"apply\":{\"JAVA\":{\"type\":\"String\"},\"MYSQL\":{\"type\":\"VARCHAR(128)\"},\"ORACLE\":{\"type\":\"NVARCHAR2(128)\"},\"SQLServer\":{\"type\":\"NVARCHAR(128)\"},\"PostgreSQL\":{\"type\":\"VARCHAR(128)\"}}},{\"name\":\"备注说明\",\"code\":\"Intro\",\"apply\":{\"JAVA\":{\"type\":\"String\"},\"MYSQL\":{\"type\":\"VARCHAR(512)\"},\"ORACLE\":{\"type\":\"NVARCHAR2(512)\"},\"SQLServer\":{\"type\":\"NVARCHAR(512)\"},\"PostgreSQL\":{\"type\":\"VARCHAR(512)\"}}},{\"name\":\"字串-短\",\"code\":\"ShortString\",\"apply\":{\"JAVA\":{\"type\":\"String\"},\"MYSQL\":{\"type\":\"VARCHAR(128)\"},\"ORACLE\":{\"type\":\"NVARCHAR2(128)\"},\"SQLServer\":{\"type\":\"NVARCHAR(128)\"},\"PostgreSQL\":{\"type\":\"VARCHAR(128)\"}}},{\"name\":\"字串-中\",\"code\":\"MiddleString\",\"apply\":{\"JAVA\":{\"type\":\"String\"},\"MYSQL\":{\"type\":\"VARCHAR(1024)\"},\"ORACLE\":{\"type\":\"NVARCHAR2(1024)\"},\"SQLServer\":{\"type\":\"NVARCHAR(1024)\"},\"PostgreSQL\":{\"type\":\"VARCHAR(1024)\"}}},{\"name\":\"字串-长\",\"code\":\"LongString\",\"apply\":{\"JAVA\":{\"type\":\"String\"},\"ORACLE\":{\"type\":\"NVARCHAR2(3072)\"},\"MYSQL\":{\"type\":\"VARCHAR(3072)\"},\"SQLServer\":{\"type\":\"NVARCHAR(3072)\"},\"PostgreSQL\":{\"type\":\"VARCHAR(3072)\"}}},{\"name\":\"大文本\",\"code\":\"LongText\",\"apply\":{\"JAVA\":{\"type\":\"String\"},\"MYSQL\":{\"type\":\"TEXT\"},\"ORACLE\":{\"type\":\"CLOB\"},\"SQLServer\":{\"type\":\"NTEXT\"},\"PostgreSQL\":{\"type\":\"TEXT\"}}},{\"name\":\"小数\",\"code\":\"Double\",\"apply\":{\"JAVA\":{\"type\":\"Double\"},\"MYSQL\":{\"type\":\"DECIMAL(32,10)\"},\"ORACLE\":{\"type\":\"NUMBER(32,10)\"},\"SQLServer\":{\"type\":\"DECIMAL(32,10)\"},\"PostgreSQL\":{\"type\":\"DECIMAL(32,10)\"}}},{\"name\":\"比例\",\"code\":\"Ratio\",\"apply\":{\"MYSQL\":{\"type\":\"DECIMAL(4,2)\"},\"JAVA\":{\"type\":\"Double\"},\"ORACLE\":{\"type\":\"NUMBER(4,2)\"},\"SQLServer\":{\"type\":\"DECIMAL(4,2)\"},\"PostgreSQL\":{\"type\":\"DECIMAL(4,2)\"}}},{\"name\":\"整数\",\"code\":\"Integer\",\"apply\":{\"JAVA\":{\"type\":\"Integer\"},\"MYSQL\":{\"type\":\"INT\"},\"ORACLE\":{\"type\":\"INT\"},\"SQLServer\":{\"type\":\"INT\"},\"PostgreSQL\":{\"type\":\"INT\"}}},{\"name\":\"大整数\",\"code\":\"BigInt\",\"apply\":{\"MYSQL\":{\"type\":\"BIGINT\"},\"JAVA\":{\"type\":\"Long\"},\"ORACLE\":{\"type\":\"NUMBER\"},\"SQLServer\":{\"type\":\"BIGINT\"},\"PostgreSQL\":{\"type\":\"BIGINT\"}}},{\"name\":\"金额\",\"code\":\"Money\",\"apply\":{\"JAVA\":{\"type\":\"Double\"},\"MYSQL\":{\"type\":\"DECIMAL(32,8)\"},\"ORACLE\":{\"type\":\"NUMBER(32,8)\"},\"SQLServer\":{\"type\":\"DECIMAL(32,8)\"},\"PostgreSQL\":{\"type\":\"DECIMAL(32,8)\"}}},{\"name\":\"是否\",\"code\":\"YesNo\",\"apply\":{\"JAVA\":{\"type\":\"String\"},\"MYSQL\":{\"type\":\"VARCHAR(1)\"},\"ORACLE\":{\"type\":\"VARCHAR2(1)\"},\"SQLServer\":{\"type\":\"VARCHAR(1)\"},\"PostgreSQL\":{\"type\":\"VARCHAR(1)\"}}},{\"name\":\"数据字典\",\"code\":\"Dict\",\"apply\":{\"JAVA\":{\"type\":\"String\"},\"MYSQL\":{\"type\":\"VARCHAR(32)\"},\"ORACLE\":{\"type\":\"VARCHAR2(32)\"},\"SQLServer\":{\"type\":\"VARCHAR(32)\"},\"PostgreSQL\":{\"type\":\"VARCHAR(32)\"}}},{\"name\":\"日期\",\"code\":\"Date\",\"apply\":{\"JAVA\":{\"type\":\"Date\"},\"MYSQL\":{\"type\":\"DATE\"},\"ORACLE\":{\"type\":\"DATE\"},\"SQLServer\":{\"type\":\"DATE\"},\"PostgreSQL\":{\"type\":\"DATE\"}}},{\"name\":\"日期时间\",\"code\":\"DateTime\",\"apply\":{\"JAVA\":{\"type\":\"Date\"},\"MYSQL\":{\"type\":\"DATETIME\"},\"ORACLE\":{\"type\":\"DATE\"},\"SQLServer\":{\"type\":\"DATE\"},\"PostgreSQL\":{\"type\":\"DATE\"}}},{\"name\":\"单字符\",\"code\":\"Char\",\"apply\":{\"MYSQL\":{\"type\":\"CHAR(1)\"},\"ORACLE\":{\"type\":\"CHAR(1)\"},\"JAVA\":{\"type\":\"String\"},\"SQLServer\":{\"type\":\"CHAR(1)\"},\"PostgreSQL\":{\"type\":\"CHAR(1)\"}}}],\"database\":[{\"code\":\"MYSQL\",\"template\":\"DROP TABLE {{=it.entity.title}};\\n$blankline\\nCREATE TABLE {{=it.entity.title}}(\\n{{ pkList = [] ; }}\\n{{~it.entity.fields:field:index}}\\n    {{? field.pk }}{{ pkList.push(field.name) }}{{?}}\\n    {{=field.name}} {{=field.type}} {{= field.pk ? 'NOT NULL' : '' }} COMMENT '{{=it.func.join(field.chnname,field.remark,';')}}' {{= index < it.entity.fields.length-1 ? ',' : ( pkList.length>0 ? ',' :'' ) }}\\n{{~}}\\n{{? pkList.length >0 }}\\n    PRIMARY KEY ({{~pkList:pkName:i}}{{= pkName }}{{= i<pkList.length-1 ? ',' : '' }}{{~}})\\n{{?}}\\n) COMMENT = '{{=it.func.join(it.entity.chnname,it.entity.remark,';') }}'\",\"fileShow\":true,\"defaultDatabase\":true,\"createTableTemplate\":\"CREATE TABLE {{=it.entity.title}}(\\n{{ pkList = [] ; }}\\n{{~it.entity.fields:field:index}}\\n    {{? field.pk }}{{ pkList.push(field.name) }}{{?}}\\n    {{=field.name}} {{=field.type}} {{= field.notNull ? 'NOT NULL' : '' }} {{= field.autoIncrement ? 'AUTO_INCREMENT' : '' }} {{= field.defaultValue ? it.func.join('DEFAULT',field.defaultValue,' ') : '' }} COMMENT '{{=it.func.join(field.chnname,field.remark,' ')}}' {{= index < it.entity.fields.length-1 ? ',' : ( pkList.length>0 ? ',' :'' ) }}\\n{{~}}\\n{{? pkList.length >0 }}\\n    PRIMARY KEY ({{~pkList:pkName:i}}{{= pkName }}{{= i<pkList.length-1 ? ',' : '' }}{{~}})\\n{{?}}\\n) COMMENT = '{{=it.func.join(it.entity.chnname,it.entity.remark,' ') }}';{{=it.separator}}\\n$blankline\\n\",\"deleteTableTemplate\":\"DROP TABLE {{=it.entity.title}};{{=it.separator}}/*SkipError*/\",\"rebuildTableTemplate\":\"create table ERD_UP_{{=it.oldEntity.title}}\\nas select * from {{=it.oldEntity.title}};{{=it.separator}}\\n$blankline\\n\\ndrop table {{=it.oldEntity.title}};{{=it.separator}}\\n$blankline\\n\\nCREATE TABLE {{=it.newEntity.title}}(\\n{{ pkList = [] ; }}\\n{{~it.newEntity.fields:field:index}}\\n    {{? field.pk }}{{ pkList.push(field.name) }}{{?}}\\n    {{=field.name}} {{=field.type}} {{= field.notNull ? 'NOT NULL' : '' }} COMMENT '{{=it.func.join(field.chnname,field.remark,';')}}' {{= index < it.newEntity.fields.length-1 ? ',' : ( pkList.length>0 ? ',' :'' ) }}\\n{{~}}\\n{{? pkList.length >0 }}\\n    PRIMARY KEY ({{~pkList:pkName:i}}{{= pkName }}{{= i<pkList.length-1 ? ',' : '' }}{{~}})\\n{{?}}\\n) COMMENT = '{{=it.func.join(it.newEntity.chnname,it.newEntity.remark,';') }}';{{=it.separator}}\\n$blankline\\n\\n{{ sameCols = it.func.intersect(it.newEntity.fields,it.oldEntity.fields) ;}}\\ninsert into {{=it.newEntity.title}}(\\n{{~sameCols:field:index}}\\n    {{=field.name}}{{? index<sameCols.length-1}},{{?}}\\n{{~}}\\n) \\nselect \\n{{~sameCols:field:index}}\\n    {{=field.name}}{{? index<sameCols.length-1}},{{?}}\\n{{~}}\\nfrom ERD_UP_{{=it.oldEntity.title}};{{=it.separator}}\\n$blankline\\n\\ndrop table ERD_UP_{{=it.oldEntity.title}};{{=it.separator}}\\n$blankline\\n{{~it.newEntity.indexs:index}}\\nALTER TABLE {{=it.newEntity.title}} ADD {{? index.isUnique}}UNIQUE{{??}}INDEX{{?}} {{=index.name}}({{=it.func.join(...index.fields,',')}});{{=it.separator}}\\n{{~}}\",\"createFieldTemplate\":\"ALTER TABLE {{=it.entity.title}} ADD COLUMN {{=it.field.name}} {{=it.field.type}} {{? it.field.notNull}}NOT NULL{{?}} {{? it.field.defaultValue}}DEFAULT {{? null==it.field.defaultValue}}NULL{{??}}'{{=it.field.defaultValue}}'{{?}}{{?}} {{? it.field.autoIncrement}}AUTO_INCREMENT{{?}} {{? it.field.pk}}PRIMARY KEY{{?}} {{? it.field.chnname}}COMMENT '{{=it.field.chnname}}'{{?}} {{? it.field.addAfter}}AFTER {{=it.field.addAfter}}{{?}};{{=it.separator}}\",\"updateFieldTemplate\":\"ALTER TABLE {{=it.entity.title}} MODIFY COLUMN {{=it.field.name}} {{=it.field.type}} {{? it.field.notNull}}NOT NULL{{?}} {{? it.field.defaultValue}}DEFAULT {{? null==it.field.defaultValue}}NULL{{??}}'{{=it.field.defaultValue}}'{{?}}{{?}} {{? it.field.autoIncrement}}AUTO_INCREMENT{{?}} {{? it.field.chnname}}COMMENT '{{=it.field.chnname}}'{{?}};{{=it.separator}}\",\"deleteFieldTemplate\":\"ALTER TABLE {{=it.entity.title}} DROP {{=it.field.name}};{{=it.separator}}\",\"deleteIndexTemplate\":\"ALTER TABLE {{=it.entity.title}} DROP INDEX {{=it.index.name}};{{=it.separator}}\",\"createIndexTemplate\":\"ALTER TABLE {{=it.entity.title}} ADD {{? it.index.isUnique}}UNIQUE{{??}}INDEX{{?}} {{=it.index.name}}({{=it.func.join(...it.index.fields,',')}});{{=it.separator}}\",\"updateTableComment\":\"ALTER TABLE {{=it.entity.title}} COMMENT '{{=it.entity.chnname}}';{{=it.separator}}\"},{\"code\":\"ORACLE\",\"template\":\"DROP TABLE {{=it.entity.title}};{{=it.separator}}\\n$blankline\\nCREATE TABLE {{=it.entity.title}}(\\n{{ pkList = [] ; }}\\n{{~it.entity.fields:field:index}}\\n    {{? field.pk }}{{ pkList.push(field.name) }}{{?}}\\n    {{=field.name}} {{=field.type}}  {{= field.pk ? 'NOT NULL' : '' }} {{= index < it.entity.fields.length-1 ? ',' : ( pkList.length>0 ? ',' :'' ) }}\\n{{~}}\\n{{? pkList.length >0 }}\\n    PRIMARY KEY ({{~pkList:pkName:i}}{{= pkName }}{{= i<pkList.length-1 ? ',' : '' }}{{~}})\\n{{?}}\\n);{{=it.separator}}\\n$blankline\\nCOMMENT ON TABLE {{=it.entity.title}} IS '{{=it.func.join(it.entity.chnname,it.entity.remark,';') }}';{{=it.separator}}\\n{{~it.entity.fields:field:index}}\\nCOMMENT ON COLUMN {{=it.entity.title}}.{{=field.name}} IS '{{=it.func.join(field.chnname,field.remark,';')}}';{{=it.separator}}\\n{{~}}\",\"createTableTemplate\":\"CREATE TABLE {{=it.entity.title}}(\\n{{ pkList = [] ; }}\\n{{~it.entity.fields:field:index}}\\n    {{? field.pk }}{{ pkList.push(field.name) }}{{?}}\\n    {{=field.name}} {{=field.type}}{{? field.defaultValue}} DEFAULT {{=field.defaultValue}}{{?}}{{= field.notNull ? ' NOT NULL' : '' }}{{= index < it.entity.fields.length-1 ? ',' : ( pkList.length>0 ? ',' :'' ) }}\\n{{~}}\\n{{? pkList.length >0 }}\\n    PRIMARY KEY ({{~pkList:pkName:i}}{{= pkName }}{{= i<pkList.length-1 ? ',' : '' }}{{~}})\\n{{?}}\\n);{{=it.separator}}\\n$blankline\\n{{? it.entity.chnname || it.entity.remark}}COMMENT ON TABLE {{=it.entity.title}} IS {{? it.entity.remark}}'{{=it.entity.remark}}'{{??}}'{{=it.entity.chnname}}'{{?}};{{=it.separator}}{{?}}\\n{{~it.entity.fields:field:index}}\\n{{? field.chnname || field.remark}}COMMENT ON COLUMN {{=it.entity.title}}.{{=field.name}} IS {{? field.remark}}'{{=field.remark}}'{{??}}'{{=field.chnname}}'{{?}};{{=it.separator}}{{?}}\\n{{~}}\",\"deleteTableTemplate\":\"DROP TABLE {{=it.entity.title}};{{=it.separator}}/*SkipError*/\\r\\n$blankline\",\"rebuildTableTemplate\":\"CREATE TABLE ERD_UP_{{=it.oldEntity.title}}\\nAS SELECT * FROM {{=it.oldEntity.title}};{{=it.separator}}\\n$blankline\\nDROP TABLE {{=it.oldEntity.title}};{{=it.separator}}\\n$blankline\\nCREATE TABLE {{=it.newEntity.title}}(\\n{{ pkList = [] ; }}{{~it.newEntity.fields:field:index}}{{? field.pk }}{{ pkList.push(field.name) }}{{?}}    {{=field.name}} {{=field.type}}{{? field.defaultValue}} DEFAULT {{=field.defaultValue}}{{?}}{{= field.notNull ? ' NOT NULL' : '' }}{{= index < it.newEntity.fields.length-1 ? ',' : ( pkList.length>0 ? ',' :'' ) }}\\n{{~}}{{? pkList.length >0 }}    PRIMARY KEY ({{~pkList:pkName:i}}{{= pkName }}{{= i<pkList.length-1 ? ',' : '' }}{{~}}){{?}}\\n);{{=it.separator}}\\n$blankline\\n{{? it.newEntity.chnname || it.newEntity.remark}}COMMENT ON TABLE {{=it.newEntity.title}} IS {{? it.newEntity.remark}}'{{=it.entity.remark}}'{{??}}'{{=it.newEntity.chnname}}'{{?}};{{?}}{{=it.separator}}\\n{{~it.newEntity.fields:field:index}}\\n{{? field.chnname || field.remark}}COMMENT ON COLUMN {{=it.newEntity.title}}.{{=field.name}} IS {{? field.remark}}'{{=field.remark}}'{{??}}'{{=field.chnname}}'{{?}};{{?}}{{=it.separator}}\\n{{~}}\\n{{ sameCols = it.func.intersect(it.newEntity.fields,it.oldEntity.fields) ;}}\\n$blankline\\nINSERT INTO {{=it.newEntity.title}}(\\n{{~sameCols:field:index}}   {{=field.name}}{{? index<sameCols.length-1}},{{?}}\\n{{~}}) \\nSELECT\\n{{~sameCols:field:index}}   {{=field.name}}{{? index<sameCols.length-1}},{{?}}\\n{{~}}FROM ERD_UP_{{=it.oldEntity.title}};{{=it.separator}}\\n\\nDROP TABLE ERD_UP_{{=it.oldEntity.title}};{{=it.separator}}\\n{{~it.newEntity.indexs:index}}\\nCREATE{{? index.isUnique}} UNIQUE{{?}} INDEX {{=index.name}} ON {{=it.newEntity.title}}({{=it.func.join(index.fields,',')}});{{=it.separator}}\\n{{~}}\",\"createFieldTemplate\":\"ALTER TABLE {{=it.entity.title}} ADD({{=it.field.name}} {{=it.field.type}}{{? it.field.defaultValue}} DEFAULT {{=it.field.defaultValue}}{{?}}{{? it.field.notNull}} NOT NULL{{?}});{{=it.separator}}\\r\\n{{? it.field.chnname || it.field.remark}}COMMENT ON COLUMN {{=it.entity.title}}.{{=it.field.name}} IS {{? it.field.remark}}'{{=it.field.remark}}'{{??}}'{{=it.field.chnname}}'{{?}};{{=it.separator}}{{?}}\\r\\n$blankline\",\"updateFieldTemplate\":\"ALTER TABLE {{=it.entity.title}} MODIFY({{=it.field.name}} {{=it.field.type}}{{? it.field.defaultValue}} DEFAULT {{=it.field.defaultValue}}{{?}}{{? it.field.notNull}} NOT NULL{{?}});{{=it.separator}}\\r\\n{{? it.field.chnname || it.field.remark}}COMMENT ON COLUMN {{=it.entity.title}}.{{=it.field.name}} IS {{? it.field.remark}}'{{=it.field.remark}}'{{??}}'{{=it.field.chnname}}'{{?}};{{=it.separator}}{{=it.separator}}{{?}}\\r\\n$blankline\",\"deleteFieldTemplate\":\"ALTER TABLE {{=it.entity.title}} DROP({{=it.field.name}});{{=it.separator}}\\r\\n$blankline\",\"deleteIndexTemplate\":\"DROP INDEX {{=it.entity.title}}.{{=it.index.name}};{{=it.separator}}\\r\\n$blankline\",\"createIndexTemplate\":\"CREATE{{? it.index.isUnique}} UNIQUE{{?}} INDEX {{=it.index.name}} ON {{=it.entity.title}}({{=it.func.join(it.index.fields,',')}});{{=it.separator}}\\r\\n$blankline\",\"updateTableComment\":\"{{? it.entity.chnname || it.entity.remark}}COMMENT ON TABLE {{=it.entity.title}} IS {{? it.entity.remark}}'{{=it.entity.remark}}'{{??}}'{{=it.entity.chnname}}'{{?}};{{=it.separator}}{{?}}\\r\\n$blankline\"},{\"code\":\"SQLServer\",\"createTableTemplate\":\"CREATE TABLE {{=it.entity.title}}(\\n{{ pkList = [] ; }}\\n{{~it.entity.fields:field:index}}\\n    {{? field.pk }}{{ pkList.push(field.name) }}{{?}}\\n    {{=field.name}} {{=field.type}} {{= field.notNull ? 'NOT NULL' : '' }} {{= field.autoIncrement ? 'IDENTITY(1,1)' : '' }} {{= field.defaultValue ? it.func.join('DEFAULT',field.defaultValue,' ') : '' }}  {{= index < it.entity.fields.length-1 ? ',' : ( pkList.length>0 ? ',' :'' ) }}\\n{{~}}\\n{{? pkList.length >0 }}\\n    CONSTRAINT PK_{{=it.entity.title}} PRIMARY KEY CLUSTERED ({{~pkList:pkName:i}}{{= pkName }} ASC {{= i<pkList.length-1 ? ',' : '' }}{{~}}) ON [PRIMARY] \\n{{?}}\\n) ;{{=it.separator}}\\n\\n$blankline\\nEXECUTE sp_addextendedproperty N'MS_Description', '{{= it.entity.chnname || it.entity.remark}}', N'user', N'dbo', N'table', N'{{=it.entity.title}}', NULL, NULL;{{=it.separator}}\\n{{~it.entity.fields:field:index}}\\n{{? field.chnname || field.remark}}EXECUTE sp_addextendedproperty N'MS_Description', {{? field.remark}}'{{=field.remark}}'{{??}}'{{=field.chnname}}'{{?}}, N'user', N'dbo', N'table', N'{{=it.entity.title}}', N'column', N'{{=field.name}}';{{=it.separator}}{{?}}\\n{{~}}\\n\"},{\"code\":\"PostgreSQL\",\"template\":\"DROP TABLE {{=it.entity.title}};\\n$blankline\\nCREATE TABLE {{=it.entity.title}}(\\n{{ pkList = [] ; }}\\n{{~it.entity.fields:field:index}}\\n    {{? field.pk }}{{ pkList.push(field.name) }}{{?}}\\n    {{=field.name}} {{=field.type}} {{= field.pk ? 'NOT NULL' : '' }} COMMENT '{{=it.func.join(field.chnname,field.remark,';')}}' {{= index < it.entity.fields.length-1 ? ',' : ( pkList.length>0 ? ',' :'' ) }}\\n{{~}}\\n{{? pkList.length >0 }}\\n    PRIMARY KEY ({{~pkList:pkName:i}}{{= pkName }}{{= i<pkList.length-1 ? ',' : '' }}{{~}})\\n{{?}}\\n) COMMENT = '{{=it.func.join(it.entity.chnname,it.entity.remark,';') }}'\",\"createTableTemplate\":\"CREATE TABLE {{=it.entity.title}}(\\n{{ pkList = [] ; }}\\n{{~it.entity.fields:field:index}}\\n    {{? field.pk }}{{ pkList.push(field.name) }}{{?}}\\n    {{=field.name}} {{=field.type}}{{? field.defaultValue}} DEFAULT {{=field.defaultValue}}{{?}}{{= field.notNull ? ' NOT NULL' : '' }}{{= index < it.entity.fields.length-1 ? ',' : ( pkList.length>0 ? ',' :'' ) }}\\n{{~}}\\n{{? pkList.length >0 }}\\n    PRIMARY KEY ({{~pkList:pkName:i}}{{= pkName }}{{= i<pkList.length-1 ? ',' : '' }}{{~}})\\n{{?}}\\n);{{=it.separator}}\\n$blankline\\n{{? it.entity.chnname || it.entity.remark}}COMMENT ON TABLE {{=it.entity.title}} IS {{? it.entity.remark}}'{{=it.entity.remark}}'{{??}}'{{=it.entity.chnname}}'{{?}};{{=it.separator}}{{?}}\\n{{~it.entity.fields:field:index}}\\n{{? field.chnname || field.remark}}COMMENT ON COLUMN {{=it.entity.title}}.{{=field.name}} IS {{? field.remark}}'{{=field.remark}}'{{??}}'{{=field.chnname}}'{{?}};{{=it.separator}}{{?}}\\n{{~}}\",\"deleteTableTemplate\":\"DROP TABLE {{=it.entity.title}};{{=it.separator}}/*SkipError*/\",\"rebuildTableTemplate\":\"create table ERD_UP_{{=it.oldEntity.title}}\\nas select * from {{=it.oldEntity.title}};{{=it.separator}}\\n$blankline\\n\\ndrop table {{=it.oldEntity.title}};{{=it.separator}}\\n$blankline\\n\\nCREATE TABLE {{=it.newEntity.title}}(\\n{{ pkList = [] ; }}\\n{{~it.newEntity.fields:field:index}}\\n    {{? field.pk }}{{ pkList.push(field.name) }}{{?}}\\n    {{=field.name}} {{=field.type}} {{= field.notNull ? 'NOT NULL' : '' }} COMMENT '{{=it.func.join(field.chnname,field.remark,';')}}' {{= index < it.newEntity.fields.length-1 ? ',' : ( pkList.length>0 ? ',' :'' ) }}\\n{{~}}\\n{{? pkList.length >0 }}\\n    PRIMARY KEY ({{~pkList:pkName:i}}{{= pkName }}{{= i<pkList.length-1 ? ',' : '' }}{{~}})\\n{{?}}\\n) COMMENT = '{{=it.func.join(it.newEntity.chnname,it.newEntity.remark,';') }}';{{=it.separator}}\\n$blankline\\n\\n{{ sameCols = it.func.intersect(it.newEntity.fields,it.oldEntity.fields) ;}}\\ninsert into {{=it.newEntity.title}}(\\n{{~sameCols:field:index}}\\n    {{=field.name}}{{? index<sameCols.length-1}},{{?}}\\n{{~}}\\n) \\nselect \\n{{~sameCols:field:index}}\\n    {{=field.name}}{{? index<sameCols.length-1}},{{?}}\\n{{~}}\\nfrom ERD_UP_{{=it.oldEntity.title}};{{=it.separator}}\\n$blankline\\n\\ndrop table ERD_UP_{{=it.oldEntity.title}};{{=it.separator}}\",\"createFieldTemplate\":\"ALTER TABLE {{=it.entity.title}} ADD COLUMN {{=it.field.name}} {{=it.field.type}} {{? it.field.notNull}}NOT NULL{{?}} {{? it.field.defaultValue}}DEFAULT {{? null==it.field.defaultValue}}NULL{{??}}'{{=it.field.defaultValue}}'{{?}}{{?}} {{? it.field.autoIncrement}}AUTO_INCREMENT{{?}} {{? it.field.pk}}PRIMARY KEY{{?}} {{? it.field.chnname}}COMMENT '{{=it.field.chnname}}'{{?}} {{? it.field.addAfter}}AFTER {{=it.field.addAfter}}{{?}};{{=it.separator}}\",\"updateFieldTemplate\":\"ALTER TABLE {{=it.entity.title}} MODIFY COLUMN {{=it.field.name}} {{=it.field.type}} {{? it.field.notNull}}NOT NULL{{?}} {{? it.field.defaultValue}}DEFAULT {{? null==it.field.defaultValue}}NULL{{??}}'{{=it.field.defaultValue}}'{{?}}{{?}} {{? it.field.autoIncrement}}AUTO_INCREMENT{{?}} {{? it.field.chnname}}COMMENT '{{=it.field.chnname}}'{{?}};{{=it.separator}}\",\"deleteFieldTemplate\":\"ALTER TABLE {{=it.entity.title}} DROP {{=it.field.name}};{{=it.separator}}\",\"deleteIndexTemplate\":\"ALTER TABLE {{=it.entity.title}} DROP INDEX {{=it.index.name}};{{=it.separator}}\",\"createIndexTemplate\":\"ALTER TABLE {{=it.entity.title}} ADD {{? it.index.isUnique}}UNIQUE{{??}}INDEX{{?}} {{=it.index.name}}({{=it.func.join(...it.index.fields,',')}});{{=it.separator}}\",\"updateTableComment\":\"ALTER TABLE {{=it.entity.title}} COMMENT '{{=it.entity.chnname}}';{{=it.separator}}\"},{\"code\":\"JAVA\",\"template\":\"package group.rober.erd.{{=it.module.name}}.entity;\\n$blankline\\nimport javax.persistence.*;\\nimport java.io.Serializable;\\nimport java.util.Date;\\n$blankline\\n$blankline\\n\\n/** {{=it.entity.chnname}} */\\n@Table(name=\\\"{{=it.entity.title}}\\\")\\npublic class {{=it.func.camel(it.entity.title,true) }} implements Serializable,Cloneable{\\n{{~it.entity.fields:field:index}}\\n    /** {{=it.func.join(field.chnname,field.remark,';')}} */\\n    {{? field.pk }}\\n    @Id\\n    @GeneratedValue\\n    {{?}}\\n    private {{=field.type}} {{=it.func.camel(field.name,false)}} ;\\n{{~}}\\n$blankline\\n{{~it.entity.fields:field:index}}\\n    /** {{=it.func.join(field.chnname,field.remark,';')}} */\\n    public {{=field.type}} get{{=it.func.camel(field.name,true)}}(){\\n        return this.{{=it.func.camel(field.name,false)}};\\n    }\\n    /** {{=it.func.join(field.chnname,field.remark,';')}} */\\n    public void set{{=it.func.camel(field.name,true)}}({{=field.type}} {{= it.func.camel(field.name,false) }}){\\n        this.{{=it.func.camel(field.name,false)}} = {{= it.func.camel(field.name,false) }};\\n    }\\n{{~}}\\n}\",\"createTableTemplate\":\"package group.rober.erd.{{=it.module.name}}.entity;\\n$blankline\\nimport javax.persistence.*;\\nimport java.io.Serializable;\\nimport java.util.Date;\\n$blankline\\n$blankline\\n@Table(name=\\\"{{=it.entity.title}}\\\")\\npublic class {{=it.func.camel(it.entity.title,true) }} implements Serializable,Cloneable{\\n{{~it.entity.fields:field:index}}\\n    /** {{=it.func.join(field.chnname,field.remark,';')}} */\\n    {{? field.pk }}\\n    @Id\\n    @GeneratedValue\\n    {{?}}\\n    private {{=field.type}} {{=it.func.camel(field.name,false)}} ;\\n{{~}}\\n$blankline\\n{{~it.entity.fields:field:index}}\\n    /** {{=it.func.join(field.chnname,field.remark,';')}} */\\n    public {{=field.type}} get{{=it.func.camel(field.name,true)}}(){\\n        return this.{{=it.func.camel(field.name,false)}};\\n    }\\n    /** {{=it.func.join(field.chnname,field.remark,';')}} */\\n    public void set{{=it.func.camel(field.name,true)}}({{=field.type}} {{= it.func.camel(field.name,false) }}){\\n        this.{{=it.func.camel(field.name,false)}} = {{= it.func.camel(field.name,false) }};\\n    }\\n{{~}}\\n}\",\"deleteTableTemplate\":\"\",\"rebuildTableTemplate\":\"\",\"createFieldTemplate\":\"\",\"updateFieldTemplate\":\"\",\"deleteFieldTemplate\":\"\",\"deleteIndexTemplate\":\"\",\"createIndexTemplate\":\"\",\"updateTableComment\":\"\"}]}}";

    @Override
    public Result projectService(String projectId) {
        Project project = this.getById(projectId);
        HashMap<String, Object> map = new HashMap<>(3);
        try {
            map.put("configJSON", JsonUtil.parse(new String(project.getConfigJSON()), Map.class));
            map.put("projectJSON", JsonUtil.parse(new String(project.getProjectJSON()), Map.class));
            map.put("projectName", project.getProjectName());
        } catch (Exception e) {
            e.printStackTrace();
            return new Result<>().error(e.getMessage());
        }
        return new Result<>(map);
    }

    @Override
    public Result saveModule(String projectId, ParseDataModel parseDataModel, String moduleName, String moduleId) {
        JsonNode jsonNode = queryProjectJsonByProjectId(projectId);
        if (jsonNode == null) {
            return new Result<>().error("jsonNode解析为空");
        }

        // new module
        JsonNode newModule = JsonUtil.parseWithoutException("{}");
        assert newModule != null;
        ((ObjectNode)newModule).put("id", moduleId);
        ((ObjectNode)newModule).put("name", moduleName);
        ((ObjectNode)newModule).put("chnname", "");
        ((ObjectNode)newModule).putPOJO("entities", parseDataModel.getModule().getEntities());
        ((ObjectNode)newModule).putPOJO("associations", new ArrayList<>());
        ((ObjectNode)newModule).putPOJO("graphCanvas", new ArrayList<>());

        // add new module to array
        ArrayNode modulesArrayNode = (ArrayNode)jsonNode.get("modules");
        modulesArrayNode.add(newModule);
        if (containDuplicateModule(modulesArrayNode)) {
            return new Result<>().error("模块名重复");
        }

        // update project json by project id
        LambdaUpdateWrapper<Project> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(Project::getId, projectId);
        updateWrapper.set(Project::getProjectJSON, jsonNode.toString().getBytes());
        this.update(updateWrapper);

        // return
        return new Result<>().success("导入DDL成功");
    }

    /**
     * queryProjectJsonByProjectId
     *
     * @param projectId projectId
     * @return Map
     */
    private JsonNode queryProjectJsonByProjectId(String projectId) {
        Project project = this.getById(projectId);
        try {
            if ("null".equals(new String(project.getProjectJSON()))) {
                return JsonUtil.parse(PROJECT_JSON);
            }

            return JsonUtil.parse(new String(project.getProjectJSON()));
        } catch (IOException e) {
            log.error(e.getMessage());
        }

        return null;
    }

    /**
     * containDuplicateModule
     *
     * @param modulesArrayNode modulesArrayNode
     * @return boolean
     */
    private boolean containDuplicateModule(ArrayNode modulesArrayNode) {
        if (modulesArrayNode.isEmpty()) {
            return false;
        }

        Map<String, Integer> cache = new HashMap<>();
        for (JsonNode jsonNode : modulesArrayNode) {
            String moduleName = jsonNode.get("name").asText();
            if (cache.putIfAbsent(moduleName, 1) != null) {
                return true;
            }
        }

        return false;
    }
}
